﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Furion;
using Furion.DataEncryption;
using Furion.DependencyInjection;
using Furion.Logging.Extensions;
using GWB.Application.System.Auth.Dtos;
using GWB.Application.System.MenuManage.MenuService;
using GWB.Application.System.RoleManage.RoleService;
using GWB.Application.System.TenantManage.TenantService;
using GWB.Application.System.UserManage.UserService;
using GWB.Core;
using GWB.Core.Common.Entity;
using GWB.Core.Enum;
using GWB.Core.TableEntity;
using GWB.Supplier;
using Mapster;
using Newtonsoft.Json;

namespace GWB.Application.System.Auth.AuthService
{
    /// <summary>
    /// 授权服务
    /// </summary>
    public class AuthService : SqlSugarDb, ITransient, IAuthService
    {

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Result<AuthOutDto>> LoginAsync(AuthInputDto input)
        {
            var result = new Result<AuthOutDto>();

            //查询用户
            var user = await Db.Queryable<User>()
                                        .Filter(null, true)
                                        .FirstAsync(x => string.Equals(x.Account, input.Account, StringComparison.CurrentCultureIgnoreCase)
                                                         && x.Password.ToLower() == MD5Encryption.Encrypt(input.Password, false).ToLower());
            if (user == null)
            {
                result.IsSuccess = false;
                result.Msg = "账号或密码错误！";
            }
            else
            {
                //user的合法性验证
                var userAuthResult = await UserAuthentication(user);
                if (!userAuthResult.IsSuccess)
                {
                    result = userAuthResult.Adapt<Result<AuthOutDto>>();
                    return result;
                }

                // 生成 token
                var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
                {
                    { "UserId", user.Id },
                    { "TenantId", user.TenantId },
                    { "Account", user.Account },
                }, 300);
                CurrentUser.AccessToken = accessToken;

                //初始化
                await InitializationCurrentUser(user.Id);
                result.Data = new AuthOutDto()
                {
                    Token = accessToken,
                };
            }
            return result;
        }






        /// <summary>
        /// 获取当前登录用户
        /// </summary>
        /// <returns></returns>
        public async Task<Result<CurrentUserDto>> GetCurrentUser()
        {
            var vv = App.User?.FindFirstValue("UserId");
            var result = new Result<CurrentUserDto>() { IsSuccess = true };
            result.Data = await InitializationCurrentUser(CurrentUser.UserId);
            return result;
        }



        /// <summary>
        /// 用户合法性验证
        /// </summary>
        /// <returns></returns>
        public async Task<Result> UserAuthentication()
        {
            return await UserAuthentication(new User()
            {
                Account = CurrentUser.Account,
                TenantId = CurrentUser.TenantId,
                Id = CurrentUser.UserId,
            });
        }

        /// <summary>
        /// 用户合法性验证
        /// </summary>
        /// <returns></returns>
        public async Task<Result> UserAuthentication(User userInput)
        {
            var result = new Result() { IsSuccess = false };

            #region 租户验证
            if (userInput.TenantId != 0)
            {
                //租户验证
                var tenant = await TenantDal.GetFirstAsync(x => x.Id == userInput.TenantId);
                if (tenant == null)
                {
                    result.Msg = "租户不存在";
                    return result;
                }
                else if (tenant.State == StateType.Disable)
                {
                    result.Msg = "租户不可用";
                    return result;
                }
                else if (tenant.ExpirationTime.HasValue && tenant.ExpirationTime.Value.Date > DateTime.Now.Date)
                {
                    result.Msg = "租户已过期";
                    return result;
                }
            }
            #endregion

            #region 用户验证
            //用户验证
            var user = await Db.Queryable<User>()
                .Filter(null, true).FirstAsync(x => x.Id == userInput.Id);
            if (user == null)
            {
                result.Msg = "用户不存在";
                return result;
            }
            else if (user.State == StateType.Disable)
            {
                result.Msg = "用户不可用";
                return result;
            }
            result.IsSuccess = true;
            #endregion

            return result;
        }




        /// <summary>
        /// 初始化用户
        /// </summary>
        /// <returns></returns>
        private async Task<CurrentUserDto> InitializationCurrentUser(long userId)
        {
            var user = await Db.Queryable<User>()
                .Filter(null, true)
                .Filter(null, true).FirstAsync(x => x.Id == userId);
            CurrentUser.OrgId = user.OrgId;
            CurrentUser.RoleId = user.RoleId;
            CurrentUser.UserDataAuth = new List<long>();
            //自己的组织
            CurrentUser.UserDataAuth.Add(CurrentUser.OrgId);

            #region 用户的菜单
            object menuList;
            //判断当前是哪个租户
            if (CurrentUser.TenantId == 0)
            {
                menuList = await App.GetService<IMenuService>().GetMenuList();
            }
            else
            {
                //判断角色
                if (CurrentUser.RoleId == 0)
                {
                    menuList = await App.GetService<ITenantService>().GetTenantMenus(CurrentUser.TenantId);
                }
                else
                {
                    menuList = await App.GetService<IRoleService>().GetRoleMenus(CurrentUser.RoleId);
                }
                menuList = MenuRecursion(menuList.Adapt<List<MenuManage.Dtos.MenuOutDto>>(), 0);
            }
            #endregion

            #region 用户的数据权限
            var userDataAuth = await App.GetService<IUserService>().GetUserDataAuth(CurrentUser.UserId);
            if (userDataAuth.Count > 0)
            {
                CurrentUser.UserDataAuth.AddRange(userDataAuth.Select(x => x.OrgId).ToList());
            }
            else
            {
                CurrentUser.UserDataAuth.AddRange(OrgDal.GetList(x => x.ParentId == CurrentUser.OrgId)
                    .Select(x => x.Id).ToList());
            }
            #endregion

            return new CurrentUserDto()
            {
                Account = CurrentUser.Account,
                OrgId = CurrentUser.OrgId,
                TenantId = CurrentUser.TenantId,
                UserId = CurrentUser.UserId,
                MenuList = menuList.Adapt<List<MenuManage.Dtos.MenuOutDto>>()
            };
        }

        /// <summary>
        /// 菜单递归
        /// </summary>
        /// <param name="data"></param>
        /// <param name="pId"></param>
        /// <returns></returns>
        private List<MenuManage.Dtos.MenuOutDto> MenuRecursion(List<MenuManage.Dtos.MenuOutDto> data, long pId)
        {
            var listData = data.Where(x => x.ParentId == pId).ToList();
            foreach (var item in listData)
            {
                item.Routes = MenuRecursion(data, item.Id);
            }
            return listData;
        }
    }


}
